/**
 * 
 */
package info.sswap.ontologies.modularity.jena;

import info.sswap.ontologies.modularity.Module;
import info.sswap.ontologies.modularity.owlapi.OWLAPIModule;
import info.sswap.ontologies.modularity.owlapi.OWLAPIToJenaTranslator;

import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.HashSet;
import java.util.Set;

import org.semanticweb.owlapi.model.OWLOntology;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.NodeIterator;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.vocabulary.RDFS;

/**
 * @author Pavel Klinov
 *
 */
public class JenaModule implements Module {

	private Model mJenaModel = null;
	private Set<URI> mSig = null;
	
	public JenaModule() {
		mJenaModel = ModelFactory.createDefaultModel();
	}
	
	public JenaModule(Model jenaModel) {
		mJenaModel = jenaModel;
	}
	
	@Override
	public Set<URI> getSignature() {
		
		if (mSig != null) {
			return mSig;
		}
		else {
			Set<String> termSet = new HashSet<String>();
			
			mSig = new HashSet<URI>();

			for (StmtIterator iter = mJenaModel.listStatements(); iter.hasNext();) {
				Statement stmt = iter.next();
				
				if (stmt.getSubject().isURIResource()) {
					termSet.add(stmt.getSubject().getURI());
				}
				
				termSet.add(stmt.getPredicate().getURI());
				
				if (stmt.getObject().isURIResource()) {
					termSet.add(stmt.getObject().asResource().getURI());
				}
			}
			
			for (String term : termSet) mSig.add(URI.create(term));
		}
		
		return mSig;
	}

	@Override
	public String getModelAPI() {
		return "JENA";
	}
	
	public Model getJenaModel() {
		return mJenaModel; 
	}

	@Override
	public URI getDefiningOntologyURI(URI term) {
		for (NodeIterator nodeIter = mJenaModel.listObjectsOfProperty(mJenaModel.createResource(term.toString()), RDFS.isDefinedBy); nodeIter.hasNext();) {
			RDFNode node = nodeIter.next();
			String annValue = node.asLiteral().getString();
			
			return URI.create(annValue);
		}
		
		return null;
	}

	@Override
	public Module union(Module module) {
		
		if ("JENA".equals(module.getModelAPI())) {
			mJenaModel = mJenaModel.union(((JenaModule)module).getJenaModel());
		}
		else if ("OWL API".equals(module.getModelAPI())) {
			OWLOntology owlapiModel = ((OWLAPIModule)module).getOWLAPIModel();
			
			mJenaModel = mJenaModel.union(new OWLAPIToJenaTranslator(owlapiModel.getOWLOntologyManager(), owlapiModel).getModel());
		}
		
		return this;
	}

	@Override
	public void write(OutputStream stream) throws IOException {
		mJenaModel.write(stream);
	}

	@Override
	public boolean isEmpty() {
		return mJenaModel.isEmpty();
	}
}
